package cn.comon.app.scan.service.impl;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.MessageDigest;
import java.text.MessageFormat;
import java.util.concurrent.CountDownLatch;
import org.apache.log4j.Logger;
import cn.comon.app.scan.component.SysConfigBean;
import cn.comon.app.scan.entity.AsReportinfo;
import cn.comon.app.scan.service.AppDownloadProcessService;
import cn.comon.app.scan.service.AsReportinfoService;
import cn.comon.app.scan.util.AnalysisApkInfo;
import cn.comon.app.scan.util.SpringContextUtil;
import cn.comon.app.scan.util.UtilTools;

/**
 * 根据举报信息提供的APP的URL，下载对应的APP软件
 * @author xujf
 *
 */
public class AppDownloadProcessServiceImpl implements AppDownloadProcessService {
	
    private AsReportinfoService asReportinfoService;
    private AsReportinfo asReportinfo;
    private static int BUFFER_SIZE = 8096;//缓冲区大小  
    private static Logger logger = Logger.getLogger(AppDownloadProcessServiceImpl.class.getName());

    public AppDownloadProcessServiceImpl(AsReportinfo asReportinfo){
        this.asReportinfo = asReportinfo;
    }

    public void run() {
        try {
        	logger.debug("开始下载【" + asReportinfo.getPackageName() + "】...");
            String fileName = "";
            String temp[] = asReportinfo.getPackageUrl().replaceAll("\\\\","/").split("/");
            if (temp.length > 1) {
                fileName = temp[temp.length - 1];
            }
            String path = MessageFormat.format("{0}\\{1}\\{2}", SysConfigBean.getProperty("app.download.path"),UtilTools.getYMD(),fileName);
            this.downloadAPP(asReportinfo.getPackageUrl(), path);
            logger.debug("下载【" + asReportinfo.getPackageName() + "】完成...");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /** 
     * 下载APP文件 
     * 
     * @param destUrl String 
     * @param filePath String 
     * @throws Exception 
     */  
    private void downloadAPP(String destUrl, String filePath) {
        asReportinfoService = (AsReportinfoService)SpringContextUtil.getBean("asReportinfoServiceImpl");
        FileOutputStream fos = null;
        BufferedInputStream bis = null;
        HttpURLConnection connection = null;
        byte[] buf = new byte[BUFFER_SIZE];
        int size = 0;
        AsReportinfo asReportinfoUpdate = new AsReportinfo();
        try {
            asReportinfoUpdate.setId(asReportinfo.getId());
            //连接有效时，url为有效，否则此url为无效连接
            connection = this.isConnect(destUrl);
            if (connection != null) {
                //获取网络输入流  
                bis = new BufferedInputStream(connection.getInputStream());  
                //建立文件  
                File file = new File(filePath);
                if(!file.exists()) {
                  if(!file.getParentFile().exists()) {
                      file.getParentFile().mkdirs();
                  }  
                  file.createNewFile();
               }
                fos = new FileOutputStream(filePath);
                //保存文件 
                while ((size = bis.read(buf)) != -1) {
                  fos.write(buf, 0, size);
                }
                fos.close();
                bis.close();
                connection.disconnect();
                
                asReportinfoUpdate.setDownloadResult(1);
                asReportinfoUpdate.setLocation(filePath);
                //fileMD
                asReportinfoUpdate.setFileMd5(this.getFileMD5(file));
                //暂时无法获取csn
                asReportinfoUpdate.setCsn("");
                String[] apkinf = AnalysisApkInfo.getAPKInfo(filePath, "");
                asReportinfoUpdate.setVcode(UtilTools.convertNnllToString(apkinf[0]));
            } else {
                //无效连接
                asReportinfoUpdate.setDownloadResult(2);
                
                asReportinfoUpdate.setLocation("");
                //fileMD
                asReportinfoUpdate.setFileMd5("");
                asReportinfoUpdate.setCsn("");
                asReportinfoUpdate.setVcode("");
            }

            asReportinfoUpdate.setLastUpdateTime(UtilTools.getTimestamp(0));

        } catch (Exception e) {
            logger.error(e);
            //下载异常发生
            asReportinfoUpdate.setDownloadResult(3);
            
            asReportinfoUpdate.setLocation("");
            //fileMD
            asReportinfoUpdate.setFileMd5("");
            asReportinfoUpdate.setCsn("");
            asReportinfoUpdate.setVcode("");
        }
        //下载完成，更新下载结果
        asReportinfoService.updateDownloadAppinfo(asReportinfoUpdate);
    }
    
    /**
     * 功能描述 : 检测当前URL是否可连接或是否有效,
     * 最多连接网络 5 次, 如果 5 次都不成功说明该地址不存在或视为无效地址.
     *
     * @param url
     *            指定URL网络地址
     *
     * @return HttpURLConnection url有效时返回连接。无效时返回null
     */
    private synchronized HttpURLConnection isConnect(String url) {
        URL urlStr;
        HttpURLConnection connection = null;
        int counts = 0;
        while (counts < 5) {
            try {
                urlStr = new URL(url);
                connection = (HttpURLConnection) urlStr.openConnection();
//              connection.setRequestMethod("GET");
                connection.setConnectTimeout(30000);
                if (connection.getResponseCode() == 200) {
                    break;
                } else {
                    counts++;
                    connection = null;
                    continue;
                }
            } catch (Exception ex) {
                counts++;
                connection = null;
                continue;
            }
        }
        return connection;
    }
    
    /**
     * 功能描述 : 获取文件的MD5
     *
     * @param file 文件名
     *
     * @return String 文件的md5值
     */
    private String getFileMD5(File file) {
        if (!file.isFile()){
          return null;
        }
        MessageDigest digest = null;
        FileInputStream in=null;
        byte buffer[] = new byte[1024];
        int len;
        try {
          digest = MessageDigest.getInstance("MD5");
          in = new FileInputStream(file);
          while ((len = in.read(buffer, 0, 1024)) != -1) {
            digest.update(buffer, 0, len);
          }
          in.close();
        } catch (Exception e) {
          e.printStackTrace();
          return null;
        }
        BigInteger bigInt = new BigInteger(1, digest.digest());
        return bigInt.toString(16);
      }
}